package com.unionftech.baselibrary.glide

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.graphics.Bitmap
import android.graphics.drawable.Drawable
import android.media.MediaScannerConnection
import android.net.Uri
import android.view.View
import android.webkit.MimeTypeMap
import android.widget.ImageView
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.bumptech.glide.Glide
import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.DecodeFormat
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.engine.GlideException
import com.bumptech.glide.load.resource.bitmap.BitmapTransformation
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions
import com.bumptech.glide.request.RequestListener
import com.bumptech.glide.request.target.Target
import com.bumptech.glide.request.transition.DrawableCrossFadeFactory
import com.bumptech.glide.util.Preconditions
import com.unionftech.baselibrary.glide.core.ImageOptions
import com.unionftech.baselibrary.glide.progress.GlideImageViewTarget
import com.unionftech.baselibrary.glide.progress.ProgressManager
import com.unionftech.baselibrary.glide.transform.BlurTransformation
import com.unionftech.baselibrary.glide.transform.BorderTransformation
import com.unionftech.baselibrary.glide.transform.CircleWithBorderTransformation
import com.unionftech.baselibrary.glide.transform.GrayScaleTransformation
import com.unionftech.baselibrary.glide.transform.RoundedCornersTransformation
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import java.net.URL

/**
 * Glide 图片请求
 */
object GlideImagerLoader {
    @SuppressLint("CheckResult")
    @JvmStatic
    fun loadImage(options: ImageOptions) {
        Preconditions.checkNotNull(options, "ImageConfigImpl is required")
        val context = options.context
        Preconditions.checkNotNull(context, "Context is required")
        Preconditions.checkNotNull(options.imageView, "ImageView is required")
        val requestsWith = glideRequests(context)
        //根据类型获取
        val glideRequest = when (options.res) {
            is String -> requestsWith.load(options.res as String)
            is Bitmap -> requestsWith.load(options.res as Bitmap)
            is Drawable -> requestsWith.load(options.res as Drawable)
            is Uri -> requestsWith.load(options.res as Uri)
            is URL -> requestsWith.load(options.res as URL)
            is File -> requestsWith.load(options.res as File)
            is Int -> requestsWith.load(options.res as Int)
            is ByteArray -> requestsWith.load(options.res as ByteArray)
            else -> requestsWith.load(options.res)
        }
        glideRequest.apply {
            //缩略图大小
            if (options.thumbnail > 0f) {
                thumbnail(options.thumbnail)
            }
            //缩略图请求
            options.thumbnailUrl?.let {
                thumbnail(glideRequests(context).load(it))
            }
            //缓存配置
            val diskCacheStrategy = when (options.diskCacheStrategy) {
                ImageOptions.DiskCache.ALL -> DiskCacheStrategy.ALL
                ImageOptions.DiskCache.NONE -> DiskCacheStrategy.NONE
                ImageOptions.DiskCache.AUTOMATIC -> DiskCacheStrategy.AUTOMATIC
                ImageOptions.DiskCache.RESOURCE -> DiskCacheStrategy.RESOURCE
                ImageOptions.DiskCache.DATA -> DiskCacheStrategy.DATA
            }
            diskCacheStrategy(diskCacheStrategy)
            //优先级
            val priority = when (options.priority) {
                ImageOptions.LoadPriority.LOW -> Priority.LOW
                ImageOptions.LoadPriority.NORMAL -> Priority.NORMAL
                ImageOptions.LoadPriority.HIGH -> Priority.HIGH
                ImageOptions.LoadPriority.IMMEDIATE -> Priority.IMMEDIATE
            }
            priority(priority)
            skipMemoryCache(options.skipMemoryCache)

            val drawableOptions = options.drawableOptions
            //设置占位符
            if (drawableOptions.placeHolderDrawable != null) {
                placeholder(drawableOptions.placeHolderDrawable)
            } else if (drawableOptions.placeHolderResId != 0) {
                placeholder(drawableOptions.placeHolderResId)
            }
            //设置错误图片
            if (drawableOptions.errorDrawable != null) {
                error(drawableOptions.errorDrawable)
            } else if (drawableOptions.errorResId != 0) {
                error(drawableOptions.errorResId)
            }
            //设置请求url为空的图片
            if (drawableOptions.fallbackDrawable != null) {
                fallback(drawableOptions.fallbackDrawable)
            } else if (drawableOptions.fallbackResId != 0) {
                fallback(drawableOptions.fallbackResId)
            }
            //图片尺寸
            val size = options.size
            size?.run {
                override(width, height)
            }
            //设置图片的解码格式
            val format = when (options.format) {
                Bitmap.Config.RGB_565 -> DecodeFormat.PREFER_RGB_565
                Bitmap.Config.ARGB_8888 -> DecodeFormat.PREFER_ARGB_8888
                else -> DecodeFormat.DEFAULT
            }
            format(format)

            //----------------图片转换设置------------------------
            if (!options.isAnim) {
                dontAnimate()
            }
            if (options.isCrossFade) {
                val fadeFactory =
                    DrawableCrossFadeFactory.Builder().setCrossFadeEnabled(true).build()
                transition(DrawableTransitionOptions.withCrossFade(fadeFactory))
            }
            if (options.centerCrop) {
                centerCrop()
            }
            if (options.isFitCenter) {
                fitCenter()
            }
            //圆形图片转换
            if (options.isCircle || options.borderWidth > 0) {
                if (options.isCircle) {
                    transform(
                        CircleWithBorderTransformation(
                            options.borderWidth,
                            options.borderColor
                        )
                    )
                } else {
                    transform(BorderTransformation(options.borderWidth, options.borderColor))
                }
            }
            //圆角图片设置
            if (options.isRoundedCorners) {
                var transformation: BitmapTransformation? = null
                //圆角会收到ImageView的ScaleType的影响
                val scaleType = options.imageView?.scaleType
                if (scaleType == ImageView.ScaleType.CENTER
                    || scaleType == ImageView.ScaleType.CENTER_CROP
                    || scaleType == ImageView.ScaleType.FIT_CENTER
                    || scaleType == ImageView.ScaleType.CENTER_INSIDE
                ) {
                    transformation = CenterCrop()
                }
                if (transformation == null) {
                    transform(
                        RoundedCornersTransformation(
                            options.roundRadius,
                            0,
                            options.cornerType
                        )
                    )
                } else {
                    transform(
                        transformation, RoundedCornersTransformation(
                            options.roundRadius,
                            0,
                            options.cornerType
                        )
                    )
                }
            }
            //模糊设置
            if (options.isBlur) {
                transform(
                    BlurTransformation(
                        options.imageView!!.context,
                        options.blurRadius,
                        options.blurSampling
                    )
                )
            }
            if (options.isGray) {
                transform(GrayScaleTransformation())
            }
            options.transformation?.run {
                transform(*this)
            }

            options.requestListener?.run {
                addListener(object : RequestListener<Drawable> {
                    override fun onLoadFailed(
                        e: GlideException?,
                        model: Any?,
                        target: Target<Drawable>?,
                        isFirstResource: Boolean
                    ): Boolean {
                        onFailAction?.invoke(e.toString())
                        return false
                    }

                    override fun onResourceReady(
                        resource: Drawable?,
                        model: Any?,
                        target: Target<Drawable>?,
                        dataSource: DataSource?,
                        isFirstResource: Boolean
                    ): Boolean {
                        onSuccessAction?.invoke(resource)
                        return false
                    }
                })
            }
            options.onProgressListener?.run {
                ProgressManager.addListener(options.res.toString(), this)
            }
            into(GlideImageViewTarget(options.imageView, options.res))
        }
    }

    /**
     * 清除本地缓存
     */
    suspend fun clearDiskCache(context: Context) = withContext(Dispatchers.IO) {
        Glide.get(context).clearDiskCache()
    }

    /**
     * 清除内存缓存
     */
    @JvmStatic
    fun clearMemory(context: Context) {
        Glide.get(context).clearMemory()
    }

    /**
     * 预加载
     */
    @JvmStatic
    fun preloadImage(context: Any?, url: String?) {
        glideRequests(context).load(url).preload()
    }

    /**
     * 重新加载
     */
    @JvmStatic
    fun resumeRequests(context: Any?) {
        glideRequests(context).resumeRequests()
    }

    /**
     * 暂停加载
     */
    @JvmStatic
    fun pauseRequests(context: Any?) {
        glideRequests(context).pauseRequests()
    }

    /**
     * 下载图片
     */
    suspend fun downloadImage(context: Context, imageUrl: String?): File? =
        withContext(Dispatchers.IO) {
            var extension = MimeTypeMap.getFileExtensionFromUrl(imageUrl)
            if (extension.isNullOrEmpty()) extension = "png"
            val file = Glide.with(context).download(imageUrl).submit().get()
            val appDir = context.getExternalFilesDir("img")
            if (!appDir!!.exists()) {
                appDir.mkdirs()
            }
            val fileName = "img_" + System.nanoTime() + "." + extension
            val targetFile = File(appDir, fileName)
            file.copyTo(targetFile)
            var mimeTypes =
                MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension)
            MediaScannerConnection.scanFile(
                context,
                arrayOf(targetFile.absolutePath),
                arrayOf(mimeTypes),
                null
            )
            return@withContext targetFile
        }

    private fun glideRequests(context: Any?): GlideRequests {
        return when (context) {
            is Context -> IGlideModule.with(context)
            is Activity -> IGlideModule.with(context)
            is FragmentActivity -> IGlideModule.with(context)
            is Fragment -> IGlideModule.with(context)
            is android.app.Fragment -> IGlideModule.with(context)
            is View -> IGlideModule.with(context)
            else -> throw NullPointerException("not support")
        }
    }
}